﻿#include "CarPos.h"


CarPos::CarPos(QWidget* parent)
	: QMainWindow(parent)
{
	ui.setupUi(this);

	QButtonGroup* group = new QButtonGroup(this);
	group->addButton(ui.btn_calibrate);
	group->addButton(ui.btn_indentify);
	ui.btn_indentify->setChecked(true);

	_settings = new QSettings("config.ini", QSettings::IniFormat);
	QString ip = _settings->value("camera/ip", "192.168.0.108").toString();

	rubberBand = nullptr;
	//抓拍，设置相机
	_capture = new Capture(1, this);
	_capture->set_identify(true);
	camera_1 = new Camera_onvif(1);
	_capture->setup_camera(camera_1);

	_cc = new CalibrateCamera();

	//1 PLC实例
	ip = _settings->value("plc/ip", "127.0.0.1").toString();
	_plc = new Plc(ip);

	tmr_capture.setInterval(100);
	tmr_capture.start();
	connect(&tmr_capture, &QTimer::timeout, this, &CarPos::action_tmr_capture);

	//2 线程
	_th_plc = new QThread(this);
	_plc->moveToThread(_th_plc);
	_th_plc->start();

	//3 信号
	//3.1 收到抓拍图
	connect(_capture, &Capture::new_picture, this, [=](MatImage mat) {
		this->_img_src = mat.image.clone();

		cv::Mat img_sw = mat.image.clone();
		//画rect
		if (_capture->get_identify()) {
			cv::rectangle(img_sw, _rect, cv::Scalar(255), 1, cv::LineTypes::LINE_8, 0);
		}
		this->showpic(img_sw, this->scene);

		});
	//收到dm值
	connect(_capture, &Capture::matrix_data, this, [=](Dm dm) {
		QString s;
		for (int num : dm.dms) {
			s.append(QString::number(num) + " ");
		}

		ui.lbl_matrix_data->setText("");
		ui.lbl_matrix_data->setText(s);

		//写PLC
		plc_rw(s);
		});
	//3.2收到plc值
	connect(_plc, &Plc::data_readed, this, [=](QString s) {
		ui.lbl_plc_data->setText(s);
		//保存上一次位置
		pos_prev = s.toFloat();
		});
	connect(_plc, &Plc::motor_stae, this, [=](bool on_or_off) {
		if (on_or_off)
			ui.lbl_motor->setText("运行");
		else
			ui.lbl_motor->setText("停止");

		});
	connect(_plc, &Plc::car_direction, this, [=](bool to_east) {
		is_to_east = to_east;
		//更新小车方向
		if (is_to_east) {
			car_direction->setPixmap(QPixmap("car_direct.png"));
		}
		else {
			car_direction->setPixmap(QPixmap("car_direct_w.png"));
		}
		});
	//3.3收到plc状态
	connect(_plc, &Plc::plc_state, this, [=](bool state) {
		if (state) {
			ui.lbl_plc_state->setStyleSheet("background-color:green");
		}
		else {
			ui.lbl_plc_state->setStyleSheet("background-color:red");
		}
		});

	//4 显示
	//4.1抓拍
	this->scene = new QGraphicsScene();
	ui.graph->setScene(this->scene);
	//ui.graph->setRubberBandSelectionMode(Qt::ItemSelectionMode::ContainsItemBoundingRect);
	ui.graph->viewport()->installEventFilter(this);
	this->scene_2 = new QGraphicsScene();
	ui.graph_2->setScene(this->scene_2);
	//4.2动画
	_scene_car = new QGraphicsScene();
	_scene_car->setSceneRect(0, 0, ui.graph_car->width(), ui.graph_car->height());
	ui.graph_car->setAlignment(Qt::AlignLeft | Qt::AlignTop);
	ui.graph_car->setScene(_scene_car);

	draw();

	//5 延时1秒登录
	QTimer::singleShot(1000, this, [this]() {
		//_capture->login();
		});

	//按钮:拍摄
	connect(ui.btnCapture, &QPushButton::clicked, this, [this]() {
		camera_1->snap(); // c1
		});

	//选项:抓拍，校正
	connect(ui.btn_calibrate, &QRadioButton::clicked, this, [this]() {
		_capture->set_identify(ui.btn_indentify->isChecked());
		});
	connect(ui.btn_indentify, &QRadioButton::clicked, this, [this]() {
		_capture->set_identify(ui.btn_indentify->isChecked());
		});

	//按钮：校正
	connect(ui.btnAddToCal, &QPushButton::clicked, this, [this]() {

		//加截图到校正列表
		cv::Mat c = _img_src(cv::Rect(_capture->_rec.x, _capture->_rec.y, _capture->_rec.width, _capture->_rec.height));

		//临时处理校正
		if (!_capture->get_identify()) {
			_cc->process(c);
		}

		});

	//按钮:保存rec位置
	connect(ui.btnIniSave, &QPushButton::clicked, this, &CarPos::save_pos);

	//6 读取ini	
	int left = _settings->value("image/left", 168).toInt();
	int top = _settings->value("image/top", 95).toInt();
	int width = _settings->value("image/width", 275).toInt();
	int height = _settings->value("image/height", 95).toInt();

	ui.rect->setText(QString("%1,%2,%3,%4").arg(left).arg(top).arg(width).arg(height));
	_capture->set_rec(cv::Rect(left, top, width, height));

	//坐标to global
	QPoint pt = ui.graph->mapTo(ui.graph, QPoint(left, top));
	_rect = cv::Rect(pt.x(), pt.y(), width, height);

}

CarPos::~CarPos()
{
	_th_plc->quit();
	_th_plc->wait();
}

//事件过滤器
bool CarPos::eventFilter(QObject* obj, QEvent* event)
{
	//按下鼠标
	if (event->type() == QEvent::MouseButtonPress) {
		QMouseEvent* evt = static_cast<QMouseEvent*>(event);

		QPoint pt = pos_scene(evt->pos());
		_capture->_rec.x = pt.x();
		_capture->_rec.y = pt.y();

		this->in_drawing = true;

		//显示橡皮筋
		_origin_last = _origin; //备份原点
		_origin = pos_global(event);

		//_origin = QPoint(pt.x() + ui.graph->geometry().x(), pt.y() + ui.graph->geometry().y());

		if (!rubberBand)
			rubberBand = new QRubberBand(QRubberBand::Rectangle, this);
		rubberBand->setGeometry(QRect(_origin, QSize()));
		rubberBand->show();

	}

	//移动鼠标
	if (event->type() == QEvent::MouseMove) {

		QPoint p = pos_global(event);
		rubberBand->setGeometry(QRect(_origin, p).normalized());

	}

	//释放鼠标
	if (event->type() == QEvent::MouseButtonRelease) {

		bool is_vlaid = true;

		this->in_drawing = false;
		QPoint p = pos_global(event); // 映射的坐标

		//w,h
		int w = p.x() - _origin.x();
		int h = p.y() - _origin.y();
		//检查坐标有效
		if (w == 0 || h == 0 || p.x() < 0 || p.y() < 0) {
			_origin = _origin_last;
			is_vlaid = false;
		}
		if (is_vlaid) {
			QPoint pt = ui.graph->mapFrom(this, _origin);
			QString s = QString("%1,%2,%3,%4")
				.arg(_capture->_rec.x)
				.arg(_capture->_rec.y)
				.arg(w)
				.arg(h);
			ui.rect->setText(s);

			_capture->_rec.width = w;
			_capture->_rec.height = h;

			//更新剪切图
			try {
				this->_img_crop = this->_img_src(cv::Rect(_capture->_rec.x, _capture->_rec.y, w, h));
				showpic(_img_crop, scene_2);
			}
			catch (cv::Exception ex) {

			}

		}
	}
	return QMainWindow::eventFilter(obj, event);
}

//移动小车
void CarPos::move_car(QVariant start, QVariant end)
{

}
//画小车地面
void CarPos::draw()
{
	int w = ui.graph_car->width();
	int y = ui.graph_car->height();

	_car = new Car(ui.graph_car->x(), ui.graph_car->width(), ui.graph);

	_ground = new Ground(ui.graph_car->width());
	int y_ground = ui.graph_car->height() - _ground->_height;
	_ground->setPos(QPoint(0, y_ground));

	int y_car = y_ground - _car->_height() - 1;
	_car->setPos(QPoint(0, y_car));
	_car->set_y(y_car);

	_scene_car->addItem(_car);
	_scene_car->addItem(_ground);

	//画方向
	if (car_direction == nullptr) {
		car_direction = new QGraphicsPixmapItem();
	}
	car_direction->setPixmap(QPixmap("car_direct.png"));
	_scene_car->addItem(car_direction);
}

// 槽：显示图片
void CarPos::showpic(cv::Mat mat, QGraphicsScene* scene) {

	QPixmap pixmap = Capture::pix_from_mt(mat);
	scene->clear();
	scene->setSceneRect(0, 0, mat.cols, mat.rows);
	scene->addPixmap(pixmap);

	scene->update();
}

//读写plc
void CarPos::plc_rw(QString value)
{
	//检查字符串
	QStringList ss = value.split(" ");
	std::vector<int> values;
	for (QString s : ss) {
		if (s.compare(" ") != 0) {
			values.push_back(s.toLong());
		}
	}

	float pos = (float)values[0];
	if (pos < 1.0f) { //读到空值
		pos = pos_prev;
	}
	//小车若向东，值只能增加
	bool is_correspond = (is_to_east && (pos < pos_prev)) || (!is_to_east && (pos > pos_prev));
	if (is_correspond) {
		qDebug() << QString("current: %1,prev: %2 ,skip %1").arg(pos).arg(pos_prev) << Qt::endl;
		return;
	}
	//写到plc
	if (_plc->is_connected()) {
		Plc_data d = { pos, QString("dm"),5 };
		_plc->to_queue(d);
	}

	//移动小车
	_car->move((int)pos);
	_car->pos_num = (int)pos;
}

//位置换算
QPoint CarPos::pos_global(QEvent* event)
{
	QMouseEvent* evt = static_cast<QMouseEvent*>(event);
	QPoint pt = evt->pos();

	QPointF pt_f = ui.graph->mapTo(this, pt);
	//QPointF pt_f = ui.graph->mapToParent(pt);
	return QPoint((int)pt_f.x(), (int)pt_f.y());
}

QPoint CarPos::pos_scene(QPoint pt)
{
	QPointF pt_f = ui.graph->mapToScene(pt);
	return QPoint((int)pt_f.x(), (int)pt_f.y());
}

//保存rec位置
void CarPos::save_pos()
{
	QString str = ui.rect->text().trimmed();
	if (str.length() == 0) return;

	QStringList strs = str.split(",");
	_settings->setValue("image/left", strs.at(0).toInt());
	_settings->setValue("image/top", strs.at(1).toInt());
	_settings->setValue("image/width", strs.at(2).toInt());
	_settings->setValue("image/height", strs.at(3).toInt());

	_settings->sync();
}

//slot 定时拍摄
void CarPos::action_tmr_capture()
{
	if (ui.chk_auto->isChecked()) {
		ui.btnCapture->click(); //点击按钮
	}

	//qDebug() << "CarPos:" << QThread::currentThreadId() << Qt::endl;
}

